package com.yong.automoguding.task;

import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.gargoylesoftware.htmlunit.BrowserVersion;
import com.gargoylesoftware.htmlunit.WebClient;
import com.gargoylesoftware.htmlunit.html.*;
import com.gargoylesoftware.htmlunit.util.NameValuePair;
import com.yong.automoguding.constant.CpDailyConstant;
import com.yong.automoguding.context.CpDailyContext;
import com.yong.automoguding.dto.CpDailyResponse;
import com.yong.automoguding.entity.CpdReportLog;
import com.yong.automoguding.entity.CpdUserInfo;
import com.yong.automoguding.exception.MogudingException;
import com.yong.automoguding.remote.CpDailyApi;
import com.yong.automoguding.service.ICpdReportLogService;
import com.yong.automoguding.service.ICpdUserInfoService;
import com.yong.automoguding.util.CpDailyUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import retrofit2.Call;
import retrofit2.Response;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * 今日校园定时任务
 *
 * @author Hes
 */
@Component
@Slf4j
public class CpDailyClockTask implements IScheduledTask {

    @Autowired
    private ICpdReportLogService cpdReportLogService;

    @Autowired
    private ICpdUserInfoService cpdUserInfoService;

    @Autowired
    private CpDailyApi cpDailyApi;

    @Override
    public void run() {

        List<CpdUserInfo> list = cpdUserInfoService.list();
        list.forEach(cpdUserInfo -> {
            CpDailyContext context = new CpDailyContext();
            context.setCookie(cpdUserInfo.getAuthCookie());
            context.setAddress(cpdUserInfo.getAddress());
            context.setUsername(cpdUserInfo.getUsername());
            context.setPassword(cpdUserInfo.getPassword());
            context.setUid(cpdUserInfo.getId());
            context.setLatitude(cpdUserInfo.getLatitude());
            context.setLongitude(cpdUserInfo.getLongitude());
            try {
                queryCollectorProcessingList(context);
                detailCollector(context);
                getFormFields(context);
                submitForm(context);
                saveToLog(context);
            } catch (Exception e) {
                context.setCookie(null);
                updateCookie(context);
                log.error("今日校园error with context: {}", context);
                log.error("今日校园error", e);
            }

        });

    }

    public void getCookie(CpDailyContext context) throws Exception{
        WebClient webClient = new WebClient(BrowserVersion.CHROME);



        webClient.getOptions().setWebSocketEnabled(false);

        webClient.getOptions().setActiveXNative(false);


        webClient.getOptions().setCssEnabled(false);
        webClient.getOptions().setThrowExceptionOnScriptError(false);
        webClient.getOptions().setThrowExceptionOnFailingStatusCode(false);

        webClient.getOptions().setRedirectEnabled(false);

        HtmlPage page = webClient.getPage("https://authserver.csmzxy.edu.cn/authserver/login?service=https%3A%2F%2Fcsmzxy.campusphere.net%2Fportal%2Flogin");

        HtmlForm form = (HtmlForm) page.getByXPath("/html/body/div[3]/div[2]/div[2]/div/div[3]/div[3]/form").get(0);

        HtmlTextInput username = (HtmlTextInput) form.getElementsByAttribute("input", "id", "username").get(0);

        HtmlPasswordInput password = (HtmlPasswordInput) form.getElementsByAttribute("input", "id", "password").get(0);

        HtmlButton button = (HtmlButton) form.getElementsByAttribute("button","type","submit").get(0);

        username.setValueAttribute(context.getUsername());
        password.setValueAttribute(context.getPassword());

        HtmlPage page1 = button.click();
        NameValuePair pair = page1.getWebResponse()
                .getResponseHeaders()
                .stream().filter(h -> "Location".equals(h.getName()))
                .findFirst()
                .orElseThrow(()->new MogudingException("获取cookie失败"));

        webClient.getPage(pair.getValue());

        String pairValue = pair.getValue();

        String cookie = pairValue.substring(pairValue.indexOf("=")+1);

        context.setCookie(CpDailyConstant.AUTH_COOKIE_PREFIX+cookie);
        webClient.close();
    }

    public void queryCollectorProcessingList(CpDailyContext context) throws Exception {
        if (!StringUtils.hasLength(context.getCookie())) {
            getCookie(context);
            updateCookie(context);
        }
        String isHandled = "isHandled";
        Map<String, Object> data = new HashMap<>(0);
        Map<String, Object> header = new HashMap<>(1);
        header.put("Cookie", context.getCookie());
        CpDailyResponse response = cpDailyApi.queryCollectorProcessingList(data, header);
        log.info("response: {}", response);
        if (!Objects.equals(response.getCode(), CpDailyConstant.CODE_SUCCESS)) {
            throw new MogudingException("请求失败:"+response.getMessage());
        }
        List<Map> rows = (List<Map>) response.getDatas().get("rows");
        if (CollectionUtils.isEmpty(rows)) {
            return;
        }
        Map map = rows.get(0);
        if (Objects.equals(map.get(isHandled),CpDailyConstant.FORM_HANDLED)) {
            log.info("表单已填");
            return;
        }
        context.setCollectWid((String) map.get("wid"));
        context.setFormWid((String) map.get("formWid"));


    }

    public void detailCollector(CpDailyContext context) throws Exception {
        if (context.getCollectWid() == null) {
            return;
        }
        Map<String, Object> data = new HashMap<>(0);
        Map<String, Object> header = new HashMap<>(1);
        header.put("Cookie", context.getCookie());
        data.put("collectorWid", context.getCollectWid());

        CpDailyResponse body = cpDailyApi.detailCollector(data, header);

        log.info("response: {}", body);
        if (!Objects.equals(body.getCode(), CpDailyConstant.CODE_SUCCESS)) {
            throw new MogudingException("请求失败:"+body.getMessage());
        }

        Map collector = (Map) body.getDatas().get("collector");

        context.setSchoolTaskWid((String) collector.get("schoolTaskWid"));

    }

    public void getFormFields(CpDailyContext context) throws Exception {
        if (context.getCollectWid() == null) {
            return;
        }
        Map<String, Object> data = new HashMap<>(0);
        Map<String, Object> header = new HashMap<>(1);
        header.put("Cookie", context.getCookie());
        data.put("collectorWid", context.getCollectWid());
        data.put("formWid", context.getFormWid());
        CpDailyResponse body = cpDailyApi.getFormFields(data, header);

        log.info("response:{}", body);
        if (!Objects.equals(body.getCode(), CpDailyConstant.CODE_SUCCESS)) {
            throw new MogudingException("请求失败:"+body.getMessage());
        }
        List<Map> rows = (List<Map>) body.getDatas().get("rows");
        CpDailyUtils.fillItemForms(rows);
        context.setForm(rows);
    }

    public void submitForm(CpDailyContext context) throws Exception {
        if (context.getSchoolTaskWid() == null) {
            return;
        }
        Map<String, Object> data = new HashMap<>(16);
        Map<String, Object> header = new HashMap<>(2);
        header.put("Cookie", context.getCookie());
        header.put("Cpdaily-Extension", CpDailyConstant.CPDAILY_EXTENSION);
        header.put("extension", "1");

        data.put("collectWid", context.getCollectWid());
        data.put("formWid", context.getFormWid());
        data.put("address", context.getAddress());
        data.put("schoolTaskWid", context.getSchoolTaskWid());
        data.put("uaIsCpadaily",true);
        data.put("form", context.getForm());
        data.put("latitude", context.getLatitude());
        data.put("longitude", context.getLongitude());

        CpDailyResponse body = cpDailyApi.submitForm(data, header);
        log.info("response: {}", body);
        if (!Objects.equals(body.getCode(), CpDailyConstant.CODE_SUCCESS)) {
            throw new MogudingException("请求失败:"+body.getMessage());
        }
    }

    public void saveToLog(CpDailyContext context) {
        if (context.getSchoolTaskWid() == null) {
            return;
        }




        CpdReportLog cpdReportLog = CpdReportLog.builder()
                .formWid(Integer.valueOf(context.getFormWid()))
                .collectWid(Integer.valueOf(context.getCollectWid()))
                .address(context.getAddress())
                .schoolTaskWid(Integer.valueOf(context.getSchoolTaskWid()))
                .uid(context.getUid())
                .build();
        cpdReportLogService.save(cpdReportLog);
    }


    /**
     * 更新cookie
     * @param context
     */
    public void updateCookie(CpDailyContext context) {


        CpdUserInfo cpdUserInfo = new CpdUserInfo();

        cpdUserInfo.setId(context.getUid());

        cpdUserInfo.setAuthCookie(context.getCookie());

        cpdUserInfoService.saveOrUpdate(cpdUserInfo);


    }



}
